﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using FFmpegVideoClip.Lib;
using static FFmpegVideoClip.Lib.VideoDetectTools;

namespace FFmpegVideoClip.windows
{
    /// <summary>
    /// VideoDetectWindow.xaml 的交互逻辑
    /// </summary>
    public partial class VideoDetectWindow : Window
    {
        public VideoDetectTools.Mode CurrentMode = VideoDetectTools.Mode.BlackdetectPic;
        public string FilePath = string.Empty;
        public double[] Result = [];
        DetectToolsData? CurrentDetect;
        private readonly object CurrentDetectDisposelockSynchronousHandle = new object();
        public bool IsEnableAutoCut => EnableCut.IsChecked ?? false;
        public bool IsEnableCutToNewClip => EnableCutToClip.IsChecked ?? false;
        private bool m_EnableTimeRange_Checked => EnableTimeRange.IsChecked ?? false;
        public VideoDetectWindow()
        {
            InitializeComponent();
            this.Loaded += VideoDetectWindow_Loaded;
        }

        private void VideoDetectWindow_Loaded(object sender, RoutedEventArgs e)
        {
            CurrentProgressBar.Visibility = Visibility.Hidden;
            Blackdetect_pix_thButton.IsChecked = true;
        }

        public DetectToolsData GetTools => CurrentMode switch
        {
            VideoDetectTools.Mode.BlackdetectPix => new BlackdetectData(double.Parse(DurationText.Text), BlackdetectData.Mode.pix_th, ValueSlider.Value),
            VideoDetectTools.Mode.Negate_BlackdetectPic=> new BlackdetectData(double.Parse(DurationText.Text), BlackdetectData.Mode.Negate_pic_th, ValueSlider.Value),
            VideoDetectTools.Mode.Negate_BlackdetectPix=> new BlackdetectData(double.Parse(DurationText.Text), BlackdetectData.Mode.Negate_pix_th, ValueSlider.Value),
            VideoDetectTools.Mode.Freezedetect => new FreezedetectData(double.Parse(DurationText.Text), ValueSlider.Value),
            VideoDetectTools.Mode.Scdet => new ScdetData(ValueSlider.Value),
            VideoDetectTools.Mode.SelectGtScene=> new SelectGtSceneData(ValueSlider.Value),
            _ => new BlackdetectData(double.Parse(DurationText.Text), BlackdetectData.Mode.pic_th, ValueSlider.Value)
        };

        private void ToolsData_ProgressValueChange(double value) { CurrentProgressBar.Dispatcher.BeginInvoke(() => CurrentProgressBar.Value = value); }

        private async void OK_Button_Click(object sender, RoutedEventArgs e)
        {
            Info.Visibility = Visibility.Collapsed;
            EnableTimeRangeHide();
            if (string.IsNullOrWhiteSpace(FilePath)||!File.Exists(FilePath))
                throw new FileNotFoundException($"路径非法或文件不存在 [{FilePath}]");
            CurrentDetect = GetTools;
            CurrentProgressBar.Visibility = Visibility.Visible;
            CurrentDetect.ProgressValueChange += ToolsData_ProgressValueChange;
            Lib.Controls.RangeSelect.SelectRange selectRange = TimeSelect.GetSelectRange();
            Result = await CurrentDetect.ExecuteAsync(FilePath,new DetectToolsData.RangeSelectData(TimeSpan.FromSeconds(selectRange.SelectMin).ToString(Tools.TimeSpan_hhmmssfff), 
                TimeSpan.FromSeconds(selectRange.SelectMax).ToString(Tools.TimeSpan_hhmmssfff), m_EnableTimeRange_Checked));

            if (m_EnableTimeRange_Checked)
                Result = Result.Select(p => p + selectRange.SelectMin).ToArray();

            CurrentProgressBar.Visibility = Visibility.Hidden;
            if (CurrentDetect == null || (CurrentDetect.CancellationTokenSource?.IsCancellationRequested ?? true))
            {
                Info.Foreground = Brushes.Red;
                Info.Text = "操作取消";
                Info.Visibility = Visibility.Visible;
                Result = [];
                EnableTimeRangeShow();
                return;
            }
            if (Result.Length < 1)
            {
                Info.Foreground = Brushes.Red;
                Info.Text = "没有有效数据";
                Info.Visibility = Visibility.Visible;
                EnableTimeRangeShow();
                return;
            }
            lock (CurrentDetectDisposelockSynchronousHandle)
            {
                if (CurrentDetect != null)
                {
                    CurrentDetect.Dispose();
                    CurrentDetect = null;
                }
            }
            this.DialogResult = true;
        }

        private void Cancel_Button_Click(object sender, RoutedEventArgs e)
        {
            if (CurrentDetect == null)
            {
                this.DialogResult = false;
                return;
            }
            Task.Run(() => {
                lock (CurrentDetectDisposelockSynchronousHandle)
                {
                    if (CurrentDetect == null)
                        return;
                    CurrentDetect.Cancel();
                    CurrentDetect.Dispose();
                    CurrentDetect = null;
                }
            });
            
        }

        private void Blackdetect_pix_thButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || Blackdetect_pix_thButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.BlackdetectPix;
            DurationText.IsEnabled = true;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = BlackdetectData.MaxPix_th;
            ValueSlider.Value = BlackdetectData.Current_Pix_th;
            DurationText.Text = Math.Round(BlackdetectData.Current_Pix_Duration, 2, MidpointRounding.AwayFromZero).ToString();
            HelpText.Text = BlackdetectData.pixValueHelp;
        }

        private void Blackdetect_pic_thButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || Blackdetect_pic_thButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.BlackdetectPic;
            DurationText.IsEnabled = true;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = BlackdetectData.MaxPic_th;
            ValueSlider.Value = BlackdetectData.Current_Pic_th;
            DurationText.Text = Math.Round(BlackdetectData.Current_Pic_Duration, 2, MidpointRounding.AwayFromZero).ToString();
            HelpText.Text = BlackdetectData.picValueHelp;
        }

        private void Negate_Blackdetect_pix_thButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || Negate_Blackdetect_pix_thButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.Negate_BlackdetectPix;
            DurationText.IsEnabled = true;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = BlackdetectData.MaxPix_th;
            ValueSlider.Value = BlackdetectData.Current_Pix_th;
            DurationText.Text = Math.Round(BlackdetectData.Current_Pix_Duration, 2, MidpointRounding.AwayFromZero).ToString();
            HelpText.Text = BlackdetectData.Negate_pixValueHelp;
        }

        private void Negate_Blackdetect_pic_thButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || Negate_Blackdetect_pic_thButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.Negate_BlackdetectPic;
            DurationText.IsEnabled = true;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = BlackdetectData.MaxPic_th;
            ValueSlider.Value = BlackdetectData.Current_Pic_th;
            DurationText.Text = Math.Round(BlackdetectData.Current_Pic_Duration, 2, MidpointRounding.AwayFromZero).ToString();
            HelpText.Text = BlackdetectData.Negate_picValueHelp;
        }

        private void FreezedetectButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || FreezedetectButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.Freezedetect;
            DurationText.IsEnabled = true;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = FreezedetectData.MaxValue;
            ValueSlider.Value = FreezedetectData.Current_SettingValue;
            DurationText.Text = Math.Round(FreezedetectData.Current_Duration, 2, MidpointRounding.AwayFromZero).ToString();
            HelpText.Text = FreezedetectData.ValueHelp;
        }

        private void ScdetButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || ScdetButton.IsChecked != true)
                return;
            Info.Visibility = Visibility.Collapsed;
            CurrentMode = VideoDetectTools.Mode.Scdet;
            DurationText.IsEnabled = false;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = ScdetData.MaxValue;
            ValueSlider.Value = ScdetData.Current;
            HelpText.Text = ScdetData.ValueHelp;
        }
        private void SelectGtSceneButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!IsLoaded || SelectGtSceneButton.IsChecked != true)
                return;
            CurrentMode = VideoDetectTools.Mode.SelectGtScene;
            DurationText.IsEnabled = false;
            ValueSlider.IsEnabled = true;
            ValueSlider.Maximum = SelectGtSceneData.MaxValue;
            ValueSlider.Value = SelectGtSceneData.Current;
            HelpText.Text = SelectGtSceneData.ValueHelp;
        }
        private static readonly Regex regex = new(@"(^\d+\.\d+$)|(^\d+\.$)|(^\d+$)|(^\.+$)", RegexOptions.CultureInvariant | RegexOptions.Compiled);


        Dictionary<TextBox, string> OldText = new Dictionary<TextBox, string>();
        private void InLimitNumbersOnly_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            if (regex.IsMatch(e.Text))
            {
                TextBox textBox = (TextBox)sender;
                OldText[textBox] = textBox.Text;
                return;
            }
            e.Handled = true;
        }

        private void NumbersFromatLimit_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textBox = (TextBox)sender;
            if (regex.IsMatch(textBox.Text))
                return;
            textBox.Text = OldText[textBox];
        }

        private void ValueSlider_TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                TextBox textBox = (TextBox)sender;
                textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
                e.Handled = true;
            }
        }

        
        private void EnableTimeRange_Checked(object sender, RoutedEventArgs e)
        {
            if (m_EnableTimeRange_Checked)
            {
                TimeSelect.Maximum = GetMediaInfo.GetInfo(FilePath).Duration.TotalSeconds;
                TimeSelect.SelectValue1 = Tools.GetStringTimeToTimeSpan(ClipManage.CurrentEditFragment.StartTimeValue).TotalSeconds;
                TimeSelect.SelectValue2 = Tools.GetStringTimeToTimeSpan(ClipManage.CurrentEditFragment.EndTimeValue).TotalSeconds;
                TimeSelect.Visibility = Visibility.Visible;
            }
        }
        private void EnableTimeRangeHide() => TimeSelect.Visibility = Visibility.Collapsed;
        private void EnableTimeRangeShow()
        {
            if(!m_EnableTimeRange_Checked)
            {
                TimeSelect.Visibility = Visibility.Collapsed;
                return;
            }
            TimeSelect.Visibility = Visibility.Visible;
        }

        private void EnableTimeRange_Unchecked(object sender, RoutedEventArgs e) => TimeSelect.Visibility = Visibility.Collapsed;
    }

    
}
